# frozen_string_literal: true

module Vulnerabilities
  class StarboardVulnerabilityCreateService < CreateServiceBase
    include Gitlab::Allowable

    CLUSTER_IMAGE_SCANNING_REPORT_TYPE = ::Enums::Vulnerability.report_types[:cluster_image_scanning]
    METADATA_VERSION = "cluster_image_scanning:1.0"

    attr_reader :agent

    def initialize(agent, params:)
      @agent = agent
      @project = agent.project
      @author = agent.created_by_user
      @params = params
    end

    def execute
      raise Gitlab::Access::AccessDeniedError unless authorized?

      vulnerability_hash = @params[:vulnerability]
      vulnerability = initialize_vulnerability(vulnerability_hash)
      identifiers = initialize_identifiers(@params.dig(:vulnerability, :identifiers))
      scanner = initialize_scanner(@params[:scanner])
      finding = initialize_finding(
        vulnerability: vulnerability,
        identifiers: identifiers,
        scanner: scanner,
        description: vulnerability_hash[:description],
        solution: vulnerability_hash[:solution]
      )

      if existing_vulnerability = Vulnerability.with_findings_by_uuid(finding.uuid).first
        return ServiceResponse.success(payload: { vulnerability: existing_vulnerability })
      end

      Vulnerability.transaction do
        vulnerability.save!
        finding.save!
        agent.update!(has_vulnerabilities: true) unless agent.has_vulnerabilities?

        Statistics::UpdateService.update_for(vulnerability)

        ServiceResponse.success(payload: { vulnerability: vulnerability })
      end
    rescue ActiveRecord::RecordInvalid => e
      ServiceResponse.error(message: e.message)
    end

    private

    def report_type
      CLUSTER_IMAGE_SCANNING_REPORT_TYPE
    end

    def metadata_version
      METADATA_VERSION
    end

    def location_fingerprint(location_hash)
      kubernetes_resource = location_hash[:kubernetes_resource]
      fingerprint_data = [
        @agent.id,
        kubernetes_resource[:namespace],
        kubernetes_resource[:kind],
        kubernetes_resource[:name],
        kubernetes_resource[:container],
        location_hash.dig(:dependency, :package, :name)
      ].join(':')

      Digest::SHA1.hexdigest(fingerprint_data)
    end

    def initialize_vulnerability(vulnerability_hash)
      vulnerability_hash[:state] = :detected
      super(vulnerability_hash)
    end
  end
end
